package com.sl.plugin.step.selenium.click;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.sl.core.engine.meta.impl.AbstractProcessCompDescriptor;
import com.sl.core.engine.step.ProcessCompService;
import com.sl.core.engine.step.impl.AbstractProcessComp;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.time.Duration;
import java.util.List;

/**
 *
 */
public class SeleniumClickComp extends AbstractProcessComp<WebDriver, WebDriver> implements ProcessCompService {

    public SeleniumClickComp(AbstractProcessCompDescriptor abstractProcessCompDescriptor) {
        super(abstractProcessCompDescriptor);
    }


    @SneakyThrows
    @Override
    public WebDriver input(WebDriver driver) {
        String textContains = meta.getStrAttr("textContains");
        String cssSelector = meta.getStrAttr("cssSelector");
        Boolean dbClickFlag = meta.getBoolAttr("dbClickFlag");

        // 初始化显式等待：最长等待10秒，每500毫秒检查一次条件
        WebElement webElement = waitForSelector(driver, cssSelector, textContains);
        Thread.sleep(1000);
        try {
            if (BooleanUtil.isTrue(dbClickFlag)) {
                // 1. 初始化 Actions 对象，关联当前驱动
                Actions actions = new Actions(driver);

// 2. 对目标元素执行双击操作
                actions.doubleClick(webElement)  // 指定双击的元素
                        .build()               // 构建动作链（可选，Selenium 3+ 可省略）
                        .perform();            // 执行动作
            } else {
                webElement.click();
            }

        } catch (Exception e) {
            // 强制转换为 JavascriptExecutor 接口
            JavascriptExecutor js = (JavascriptExecutor) driver;
            if (BooleanUtil.isTrue(dbClickFlag)) {
                js.executeScript("""
                            // 创建双击事件
                            const event = new MouseEvent('dblclick', {
                                bubbles: true,
                                cancelable: true,
                                view: window
                            });
                            // 向目标元素派发事件
                            arguments[0].dispatchEvent(event);
                        """, webElement);
            } else {
                // 使用 JavaScript 强制点击元素
                js.executeScript("arguments[0].click();", webElement);
            }


        }

        return driver;
    }

    private WebElement waitForSelector(WebDriver driver, String cssSelector, String textContains) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
        WebElement element = null;
        try {
            if (
                    StrUtil.isBlank(textContains)
            ) {
                element = wait.until(
                        ExpectedConditions.presenceOfElementLocated(By.cssSelector(cssSelector))
                );
            } else {
                element = wait.until((d) -> {
                    List<WebElement> el = d.findElements(By.cssSelector(cssSelector));
                    WebElement webElement = el.stream().filter(v -> {
                        String elementText = v.getText();
                        boolean contains = elementText.contains(textContains);

                        return contains;
                    }).findFirst().orElse(null);
                    return webElement;
                });

            }


        } catch (Exception e) {
            element = waitForSelector(driver, cssSelector, textContains);
        }
        return element;
    }
}
